
using Bee.Base.Abstractions;
using Bee.Base.Abstractions.Tasks;
using Bee.Base.Models.Tasks;
using Bee.Plugin.Multimedia.Models;

using FFMpegCore;

using Ke.Bee.Localization.Localizer.Abstractions;

using LanguageExt;

using Microsoft.Extensions.Logging;

namespace Bee.Plugin.Multimedia.Tasks;

/// <summary>
/// 视频转码
/// </summary>
/// <param name="coverHandler"></param>
/// <param name="localizer"></param>
public class VideoTranscodingTaskHandler(ICoverHandler coverHandler, ILocalizer localizer, ILogger<VideoTranscodingTaskHandler> logger) :
    TaskHandlerBase<VideoTranscodingArguments>(coverHandler)
{
    private readonly ILocalizer _l = localizer;
    private readonly ILogger<VideoTranscodingTaskHandler> _logger = logger;

    public override async Task<Fin<Unit>> ExecuteAsync(TaskItem taskItem,
        VideoTranscodingArguments arguments,
        Action<double> progressCallback,
        CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        // 分析原视频信息
        var analysis = FFProbe.Analyse(taskItem.Input);

        var fileName = Path.GetFileNameWithoutExtension(taskItem.Input);

        // 输出文件
        var outputFile = Path.Combine(arguments.OutputDirectory,
            $"{fileName}.{arguments.OutputFormat}")
            ;

        //var timeDone = TimeSpan.Zero;

        try
        {
            await FFMpegArguments.FromFileInput(taskItem.Input)
                .OutputToFile(outputFile, arguments.Overwrite, ffArgs =>
                {
                    // 指定编码器
                    if (arguments.CodecIndex is short codecIndex && codecIndex > -1)
                    {
                        ffArgs.WithVideoCodec(FFMpeg.GetCodec(MultimediaProcessConsts.AvailableVideoCodecs[codecIndex].Name));
                    }

                    /*
                    // 移除黑帧
                    if (arguments.RemoveBlackFrame)
                    {
                        ffArgs.WithVideoFilters(opts =>
                        {
                            // 检测黑帧
                            opts.BlackFrame();
                            opts.Arguments.Add(new BlackFramePBlackArgument());
                        });
                    }
                    */

                    // 缩放分辨率
                    if (arguments.ResolutionIndex is short resolutionIndex && resolutionIndex > -1)
                    {
                        var (width, height) = ParseResolution(MultimediaProcessConsts.AvailableScaleResolutions[resolutionIndex]);
                        ffArgs.WithVideoFilters(opts =>
                        {
                            opts.Scale(width, height);
                        });
                    }

                    // 帧速率
                    if (arguments.FpsIndex is short fpsIndex && fpsIndex > -1)
                    {
                        ffArgs.WithFramerate(MultimediaProcessConsts.AvailableFpsList[fpsIndex]);
                    }

                    // 静音
                    if (arguments.Mute is bool mute && mute)
                    {
                        ffArgs.WithCustomArgument("-an");
                    }

                    // 结尾插入时长为5秒的黑帧
                    //ffArgs.WithCustomArgument("-f lavfi -i color=c=black:s=3840x2160:d=5 -filter_complex \"[0:v][1:v]concat=n=2:v=1:a=0\"");
                })
                .NotifyOnProgress(progressCallback, analysis.Duration)
                /*
                .NotifyOnProgress(time =>
                {
                    if (time < analysis.Duration)
                    {
                        timeDone = time;
                        Console.WriteLine(timeDone);
                    }
                })
                */
                .ProcessAsynchronously()
                ;

        }
        catch (Exception e)
        {
            _logger.LogError(e, e.Message);
            return Fin<Unit>.Fail($"{_l["Task.Execution.Failed"]}, {fileName}");
        }

        return Fin<Unit>.Succ(Unit.Default);
    }

    /// <summary>
    /// 字符串类型的分辨率转换为元组类型
    /// </summary>
    /// <param name="resolution"></param>
    /// <returns></returns>
    /// <exception cref="FormatException"></exception>
    private Tuple<int, int> ParseResolution(string resolution)
    {
        // Split the string at the 'x' character.
        string[] parts = resolution.Split('x');

        // Check if we have exactly two parts after splitting.
        if (parts.Length != 2)
        {
            throw new FormatException(_l["Bee.Plugin.Multimedia.Resolution.Format.Failed"]);
        }

        // Try to parse the parts into integers.
        if (int.TryParse(parts[0].Trim(), out int width) &&
            int.TryParse(parts[1].Trim(), out int height))
        {
            return new Tuple<int, int>(width, height);
        }
        else
        {
            throw new FormatException(_l["Bee.Plugin.Multimedia.Resolution.NonInteger"]);
        }
    }
}

/*
/// <summary>
/// 黑帧参数
/// </summary>
public class BlackFramePBlackArgument : IVideoFilterArgument
{
    public string Key => "metadata";

    public string Value => "select:key=lavfi.blackframe.pblack:value=2:function=less";
}
*/